/** ****************************************************************************
@addtogroup RcCodec 遥控编解码器
@{
*******************************************************************************/

#ifndef __RC_CODEC_H
#define __RC_CODEC_H

#include "stdc.h"
#include "std_type.h"


// 最大逻辑编码(有效bit)长度
#define CCODE_MAX_LEN	252
// 最小逻辑编码(有效bit)长度
#define CCODE_MIN_LEN	32

//
// 脉冲缓冲区
//
/// 脉冲缓冲区
typedef struct {
	/// 下一个脉冲位置
	uint16_t next;
	/// 有效脉冲个数
	uint16_t plen;
	/// 脉冲缓冲区(脉冲宽度，单位us)
	uint16_t pulses[CCODE_MAX_LEN];
} rc_pulse_buffer_t;

// 获得第 idx 个脉冲宽度
/// @return 0: 表示结束
static inline uint16_t rc_pulse_buffer_get(rc_pulse_buffer_t *pb, uint16_t idx) { return (idx >= pb->plen) ? 0: (pb->next = idx+1, pb->pulses[idx]); }
/// 获得下一个脉冲宽度
/// @return 0: 表示结束
static inline uint16_t rc_pulse_buffer_next(rc_pulse_buffer_t *pb) { return (pb->next >= pb->plen) ? 0: pb->pulses[pb->next++]; }

//
// 脉冲索引码 编解码
//
/// 一种编码最多只允许有多少种不同的脉冲宽度
#define CCODE_MAX_PULSE_WIDTH_TYPE	8

/// 编解码错误码
typedef enum {
	RcCodecError_OK 					= 0,
	RcCodecError_TOO_MANY_PULSE_TYPE 	= -1,
	RcCodecError_TOO_MANY_PULSE		 	= -2,
	RcCodecError_UNKNWON_RCTYPE 		= -3,
	RcCodecError_UNKNWON_IFTYPE 		= -5,
	RcCodecError_UNKNWON_BIT_TYPE       = -6, // 无法找到正确的 bit 编码方式
	RcCodecError_LOW_COEFF 				= -7,
	RcCodecError_BUFFER_OVERFLOW		= -10,
	RcCodecError_BUFFER_UNDERFLOW		= -11,
	RcCodecError_INVALID_INDEX			= -12,
	RcCodecError_TOO_MANY_MC			= -15,
	RcCodecError_TOO_MANY_BIT_TYPE		= -17,
	RcCodecError_TRANS_FAILED			= -20,
	RcCodecError_EMIT_FAILED			= -22,
} RcCodecError;

/// 脉冲索引码
typedef struct {
	/// 脉宽类型数量
	uint8_t pwtc;
	/// 脉宽类型表：总共有多少种电平宽度(us)？
	/// 取的是统计平均值(us)
	uint16_t pwt[CCODE_MAX_PULSE_WIDTH_TYPE];
	
	/// 脉冲(索引)数量
	uint8_t plen;
	/// 脉冲对应的脉宽索引
	uint8_t pwi[CCODE_MAX_LEN];
	
	/// 下一个脉冲位置
	uint16_t next;
} rc_pulse_index_code_t;

/// 获得第 idx 个脉冲宽度
/// @return 0: 表示结束
static inline uint16_t rc_pulse_index_code_get(rc_pulse_index_code_t *pic, uint16_t idx) { return (idx >= pic->plen) ? 0 : (pic->next = idx+1, pic->pwt[pic->pwi[idx]]); }
/// 获得下一个脉冲宽度
/// @return 0: 表示结束
static inline uint16_t rc_pulse_index_code_next(rc_pulse_index_code_t *pic) { return (pic->next >= pic->plen) ? 0 : pic->pwt[pic->pwi[pic->next++]]; }

/// @brief 对脉冲缓冲区进行解析，并编码为脉冲索引码
/// @param pb [in] 原始脉冲缓冲区
/// @param totalWidth 脉冲总宽度(us)
/// @param pwerr 脉冲分组时，组间脉宽最小差距(%)
/// @param pic [out] 脉冲索引码
/// @param co [out] 置信度(%)
/// @return 错误码
RcCodecError rc_pulse_index_code_parse(rc_pulse_buffer_t* pb, uint32_t totalWidth, uint8_t pwerr, rc_pulse_index_code_t *pic, uint8_t *co);

/// @brief 将脉冲索引码保存到一个流式缓冲区中，以便数据传输和保存
/// @return len [in, out] (in)缓冲区大小 / (out)实际占用的字节数
/// @return 错误码
RcCodecError rc_pulse_index_code_pack(rc_pulse_index_code_t *pic, uint8_t *data, uint16_t *len);
/// @brief 将脉冲索引码从一个流式缓冲区中取出，以便进行遥控
/// @return 错误码
RcCodecError rc_pulse_index_code_unpack(const uint8_t *data, uint16_t len, rc_pulse_index_code_t *pic);

//
// Bit 码编解码
//
/// BIT 码码型
typedef enum {
	BitType_XY_YX			= 0x00,	///< XY/YX 型
	BitType_XX_XY			= 0x01,	///< XX/XY 型
	BitType_XX_YY			= 0x02,	///< XX/YY 型?
} BitType;

/// 编码类型
typedef enum {
	RcCodeType_RAW			= 0x00,	///< 原始编码
	RcCodeType_PULSE_INDEX	= 0x01,	///< 脉冲索引码
	RcCodeType_BIT			= 0x02,	///< BIT码
	RcCodeType_HXDIR		= 0x04,	///< 宏信达 红外
} RcCodeType;

/// 遥控接口类型
typedef enum {
	RcIfType_RF315			= 0x10,	///< 315 MHz
	RcIfType_RF433			= 0x20,	///< 433 MHz
	RcIfType_IR				= 0x30,	///< Ir 红外
	RcIfType_HXDIR			= 0x40,	///< 宏信达 红外
} RcIfType;

typedef struct {
	/// 数据主码(主脉宽)类型数量
	uint8_t mctc;
	/// 主码索引
	uint8_t mcxi, mcyi;
	/// 主码 Bit 码型
	BitType mcbt;
} rc_bitcode_parser_t;

/// @brief 对脉冲进行分析和编码，并通过通信接口上报
/// @param pwerr: 脉冲分组时，组间脉宽最小差距(%)
/// @param coeff: 可接受的置信度
/// @return 错误码
RcCodecError rc_bitcode_parse(rc_pulse_buffer_t* pb, uint8_t ifType, uint8_t pwerr, uint8_t coeff);

/// @brief 把编码解码成脉冲索引码，并通过遥控接口发送出去
/// @return 错误码
RcCodecError rc_decode(uint8_t* buff, uint8_t len);

/// @brief 脉冲索引码 编码为 Bit码
/// @return 错误码
RcCodecError packBitCode(rc_pulse_index_code_t *pic, uint8_t data[], uint16_t *len);

/// @brief Bit码解码为脉冲索引码
/// @return 错误码
RcCodecError unpackBitCode(uint8_t data[], uint16_t len, rc_pulse_index_code_t *pic);;

//
// 通用
//
/// @brief 通用编码获取
uint16_t rc_code_get(RcCodeType codeType, const void *code, uint16_t idx);
/// @brief 通用编码获取
uint16_t rc_code_next(RcCodeType codeType, const void *code);
/// @brief 通用 dump
void rc_code_dump(RcCodeType codeType, const void *code);


#endif  // __RC_CODEC_H
/// @}
